package com.shuyu.common.utils.nft;

import com.blockchain.tools.eth.codec.EthAbiCodecTool;
import com.blockchain.tools.eth.contract.template.ERC721Contract;
import com.blockchain.tools.eth.contract.util.EthContractUtil;
import com.blockchain.tools.eth.contract.util.model.SendModel;
import com.blockchain.tools.eth.contract.util.model.SendResultModel;
import com.shuyu.common.constant.Constants;
import com.shuyu.common.utils.nft.domain.NFTVo;
import com.shuyu.common.utils.nft.domain.WalletVo;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Numeric;

import java.io.File;
import java.math.BigInteger;

public class NFTUtils {

    //查询
    public static void queryNFT() throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://node.lingjingchain.cn"));
        ERC721Contract erc721Contract = ERC721Contract.builder(web3j, Constants.CONTRACT_ADDRESS);
        BigInteger amount = erc721Contract.balanceOf(Constants.WALLET_ADDRESS);
        System.out.println(amount);
        String owner = erc721Contract.ownerOf(BigInteger.valueOf(3));
        System.out.println(owner);
        String Approved = erc721Contract.getApproved(BigInteger.valueOf(3));
        System.out.println(Approved);
    }

    //生成NFT
    public static NFTVo createNFT(String metadata, String contractAddress) throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://node.lingjingchain.cn"));
        EthContractUtil ethContractUtil = EthContractUtil.builder(web3j);
        // Write data to the contract
        SendResultModel sendResultModel = ethContractUtil.sendRawTransaction(
                SendModel.builder()
                        .setSenderAddress(Constants.WALLET_ADDRESS) // Address of the caller
                        .setPrivateKey(Constants.PRIVATE_KEY)// Private key of senderAddress
                        .setToAddress(contractAddress) // Contract Address
                        .setChainId(1888)
                ,
                EthAbiCodecTool.getInputData(
                        "mintNFT", // Name of the method to be called
                        new Address(Constants.WALLET_ADDRESS), // Parameter 1
                        new Utf8String(metadata) // Parameter 2，If there are other parameters, you can go ahead and pass in the next
                ) // The inputData of the method to be called
        );
        EthSendTransaction transaction = sendResultModel.getEthSendTransaction(); // Results after sending a transaction
//        System.out.println(transaction.getTransactionHash());
        TransactionReceipt receipt = sendResultModel.getEthGetTransactionReceipt();// Results after the transaction is broadcast
//        System.out.println(receipt);
        String signature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
        BigInteger tokenId = null;
        for (Log log : receipt.getLogs()) {
            if(log.getTopics().get(0).equals(signature)){
                tokenId = new BigInteger(Numeric.cleanHexPrefix(log.getTopics().get(3)), 16);
            }
        }
//        System.out.println(receipt.getLogs());
        return new NFTVo(tokenId, transaction.getTransactionHash());
    }

    //交易
    public static String transactionNFT(String fromAddress, String privateKey, String toAddress, BigInteger tokenId) throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://node.lingjingchain.cn"));
//        EthChainId ethChainId = web3j.ethChainId().sendAsync().get();
//        BigInteger chainId = ethChainId.getChainId();
//        System.out.println("chainId:"+chainId);
        ERC721Contract erc721Contract = ERC721Contract.builder(web3j, Constants.CONTRACT_ADDRESS);
        SendResultModel resultModel = erc721Contract.transferFrom(fromAddress,
                toAddress,
                tokenId,
                SendModel.builder()
                        .setSenderAddress(fromAddress)
                        .setPrivateKey(privateKey)
                        .setChainId(1888));
        if(resultModel != null) {
            EthSendTransaction transaction = resultModel.getEthSendTransaction(); // Results after sending a transaction
            System.out.println(transaction.getTransactionHash());
            TransactionReceipt receipt = resultModel.getEthGetTransactionReceipt();// Results after the transaction is broadcast
            System.out.println(receipt);
            return transaction.getTransactionHash();
        } else {
            System.out.println("error");
            return "transfer error";
        }
    }


    //生成钱包
    public static WalletVo createWallet() throws Exception {
        String ethKeystorePath = "/mnt/soft/didol/wallet/";
        String password = "12345678";
        String filename = WalletUtils.generateNewWalletFile(password, new File(ethKeystorePath), true);
        String fileUrl = ethKeystorePath + filename;
        Credentials credentials = WalletUtils.loadCredentials(password, new File(fileUrl));
        String address = credentials.getAddress();
        String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);//私钥
        System.out.println("address: " + address + ", privateKey: " + privateKey);
        return new WalletVo(address, privateKey);

//        //生成带助记词的钱包
//        Bip39Wallet wallet = WalletUtils.generateBip39Wallet(password, new File(ethKeystorePath));
//        System.out.println(wallet.getMnemonic());
//        System.out.println(wallet.getFilename());


//        //加载钱包
//        Credentials credentials = WalletUtils.loadBip39Credentials(password,"glance dolphin shed weasel alone unit pass before dragon anxiety cover degree");
//        System.out.println(credentials.getAddress());
//        System.out.println(credentials.getEcKeyPair().getPrivateKey().toString(16));
    }
    public static void loadWallet() throws Exception {
        String password = "12345678";
        //加载钱包
        Credentials credentials = WalletUtils.loadBip39Credentials(password,"glance dolphin shed weasel alone unit pass before dragon anxiety cover degree");
        System.out.println(credentials.getAddress());
        System.out.println(credentials.getEcKeyPair().getPrivateKey().toString(16));
    }

    public static void main(String[] args) throws Exception {
//        transactionNFT(Constants.WALLET_ADDRESS,"0xf74e770c3fa147fed52d7eed44a0711ebe00bbd8ee6a53c01d1ee7b8f2e24d37","0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199",BigInteger.valueOf(10));
//        createWallet();
        System.out.println(createNFT("{\n" +
                "                \"tokenId\": \"my2401049\",\n" +
                "                \"name\": \"敦煌金刚力士卡牌#my2401049\",\n" +
                "                \"image\": \"https://dh-dc.oss-cn-hangzhou.aliyuncs.com/331503364741402624.gif\",\n" +
                "                \"description\": \"\",\n" +
                "                \"code\": \"0\"\n" +
                "}",Constants.CONTRACT_ADDRESS));
    }
}
